package com.zuoyy.admin.system.controller;

import com.zuoyy.admin.common.BaseController;
import com.zuoyy.admin.system.dto.UserDTO;
import com.zuoyy.common.constant.AdminConst;
import com.zuoyy.common.enums.ResultEnum;
import com.zuoyy.common.enums.StatusEnum;
import com.zuoyy.common.exception.ResultException;
import com.zuoyy.common.utils.EntityBeanUtil;
import com.zuoyy.common.utils.StatusUtil;
import com.zuoyy.common.vo.JsonResponse;
import com.zuoyy.admin.common.component.actionLog.action.StatusAction;
import com.zuoyy.admin.common.component.actionLog.action.UserAction;
import com.zuoyy.admin.common.component.actionLog.annotation.ActionLog;
import com.zuoyy.admin.common.component.actionLog.annotation.EntityParam;
import com.zuoyy.admin.common.component.shiro.ShiroUtil;
import com.zuoyy.modules.system.domain.Dept;
import com.zuoyy.modules.system.domain.Post;
import com.zuoyy.modules.system.domain.Role;
import com.zuoyy.modules.system.domain.User;
import com.zuoyy.modules.system.query.PostQuery;
import com.zuoyy.modules.system.query.RoleQuery;
import com.zuoyy.modules.system.query.UserQuery;
import com.zuoyy.modules.system.service.DeptService;
import com.zuoyy.modules.system.service.PostService;
import com.zuoyy.modules.system.service.RoleService;
import com.zuoyy.modules.system.service.UserService;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;

@Controller
@RequestMapping("/system/user")
public class UserController extends BaseController {

    //页面地址
    private static final String PAGE_PATH = "system/user";
    //权限标示
    private static final String PERMISSION_FLAG = "system:user:";


    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private DeptService deptService;
    @Autowired
    private PostService postService;

    @GetMapping("/index.shtml")
    @RequiresPermissions(PERMISSION_FLAG+"index")
    public String index(Model model, HttpServletRequest request, HttpServletResponse response) {
        model.addAttribute("res", getMyResources(request,response));
        return PAGE_PATH+"/index";
    }


    @GetMapping("/list/page")
    @RequiresPermissions(PERMISSION_FLAG+"list")
    public String listPage(Model model) {
        model.addAttribute("button", getPageButton(PERMISSION_FLAG+"list"));
        return PAGE_PATH+"/list";
    }

    @ResponseBody
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    public JsonResponse getListPage(UserQuery query){
        List<UserDTO> list = new ArrayList<UserDTO>();
        Page<User> page = userService.getPageList(query);
        List<User> users = page.getContent();
        if(users!=null&&users.size()>0){
            for(User user:users){
                UserDTO dto = new UserDTO();
                try {
                    BeanUtils.copyProperties(dto,user);
                } catch (Exception e) {
                }
                Role role = user.getRoles().stream().findFirst().orElse(null);
                dto.setRoleTitle(role.getTitle());
                dto.setRoleName(role.getName());
                if(StringUtils.isNotBlank(user.getDeptId())){
                    Dept dept = deptService.findById(user.getDeptId());
                    dto.setDeptName(dept.getDeptName());
                }
                if(StringUtils.isNotBlank(user.getPostId())){
                    Post post = postService.findById(user.getPostId());
                    dto.setPostName(post.getPostName());
                }
                list.add(dto);
            }
        }
        return JsonResponse.success(setQueryResult(query.getDraw(), (int) page.getTotalElements(),list));
    }

    @GetMapping("/add/page")
    @RequiresPermissions(PERMISSION_FLAG+"add")
    public String toAdd(Model model,String deptId) {
        List<Role> roleList = roleService.findByQuery(new RoleQuery());
        roleList = roleList.stream().filter(o -> !Arrays.asList(AdminConst.ADMIN_ROLE_List).contains(o.getId())).collect(Collectors.toList());
        roleList.sort(Comparator.comparing(Role::getCreateDate).reversed());
        model.addAttribute("roleList",roleList);
        PostQuery query = new PostQuery();
        List<Post> postList = postService.findByQuery(query);
        model.addAttribute("postList",postList);
        User dto = new UserDTO();
        dto.setDeptId(deptId);
        model.addAttribute("dto", dto);
        return PAGE_PATH+"/add";
    }


    @GetMapping("/edit/page/{id}")
    @RequiresPermissions(PERMISSION_FLAG+"edit")
    public String toEdit(@PathVariable("id") User dto, Model model) {
        model.addAttribute("dto", dto);
        List<Role> roleList = roleService.findByQuery(new RoleQuery());
        roleList = roleList.stream().filter(o -> !Arrays.asList(AdminConst.ADMIN_ROLE_List).contains(o.getId())).collect(Collectors.toList());
        roleList.sort(Comparator.comparing(Role::getCreateDate).reversed());
        model.addAttribute("roleList",roleList);
        PostQuery query = new PostQuery();
        List<Post> postList = postService.findByQuery(query);
        model.addAttribute("postList",postList);
        return PAGE_PATH+"/add";
    }

    @ResponseBody
    @PostMapping("/save")
    @RequiresPermissions({PERMISSION_FLAG+"add", PERMISSION_FLAG+"edit"})
    @ActionLog(key = UserAction.USER_SAVE, action = UserAction.class)
    public JsonResponse save(@EntityParam @RequestBody User user) {
        if (StringUtils.isEmpty(user.getId())) {
            String password = user.getUsername();
            // 对密码进行加密
            String salt = ShiroUtil.getRandomSalt();
            String encrypt = ShiroUtil.encrypt(password, salt);
            user.setPassword(encrypt);
            user.setSalt(salt);
        }
        // 判断用户名是否重复
        if (userService.repeatByUsername(user)) {
            throw new ResultException(ResultEnum.USER_EXIST);
        }
        // 复制保留无需修改的数据
        if (StringUtils.isNotBlank(user.getId())) {
            // 不允许操作超级管理员数据
            if (user.getId().equals(AdminConst.ADMIN_ID) &&
                    !ShiroUtil.getSubject().getId().equals(AdminConst.ADMIN_ID)) {
                throw new ResultException(ResultEnum.NO_ADMIN_AUTH);
            }

            User beUser = userService.findById(user.getId());
            String[] fields = {"password", "salt", "picture"};
            EntityBeanUtil.copyProperties(beUser, user, fields);
        }
        // 保存数据
        userService.save(user);
        return JsonResponse.success();
    }



    @GetMapping("/detail/page/{id}")
    @RequiresPermissions(PERMISSION_FLAG+"detail")
    public String toDetail(@PathVariable("id") User user, Model model){
        UserDTO dto = new UserDTO();
        String[] fields = {"password", "salt", "picture"};
        EntityBeanUtil.copyProperties(dto, user, fields);
        dto.setDeptName(deptService.findById(user.getDeptId()).getDeptName());
        dto.setPostName(postService.findById(user.getPostId()).getPostName());
        dto.setRoleName(user.getRoles().stream().findFirst().orElse(null).getName());
        model.addAttribute("user",dto);
        return PAGE_PATH+"/detail";
    }


    @ResponseBody
    @RequestMapping("/status/{param}")
    @ActionLog(name = "用户状态", action = StatusAction.class)
    public JsonResponse updateStatus(
            @PathVariable("param") String param,
            @RequestParam(value = "ids", required = false) List<String> ids) {
        // 不能修改超级管理员状态
        if (ids.contains(AdminConst.ADMIN_ID)) {
            throw new ResultException(ResultEnum.NO_ADMIN_STATUS);
        }
        // 更新状态
        StatusEnum statusEnum = StatusUtil.getStatusEnum(param);
        if (userService.updateStatus(statusEnum, ids)) {
            return JsonResponse.success(statusEnum.message + "成功");
        } else {
            return JsonResponse.error(statusEnum.message + "失败，请重新操作");
        }
    }

    @GetMapping("/profile/page/{id}")
    public String toProfile(@PathVariable("id") User user, Model model) throws InvocationTargetException, IllegalAccessException {
        UserDTO dto = new UserDTO();
        org.springframework.beans.BeanUtils.copyProperties(user,dto);
        dto.setDeptName(deptService.findById(user.getDeptId()).getDeptName());
        dto.setPostName(postService.findById(user.getPostId()).getPostName());
        dto.setRoleName(user.getRoles().stream().findFirst().orElse(null).getTitle());
        model.addAttribute("user",dto);
        return PAGE_PATH+"/myProfile";
    }

    @GetMapping("/updatePassword/page/{id}")
    public String toUpdatePassword(@PathVariable("id") User user, Model model) throws InvocationTargetException, IllegalAccessException {
        model.addAttribute("user",user);
        return PAGE_PATH+"/updatePassword";
    }

    @ResponseBody
    @PostMapping("/updatePassword")
    public JsonResponse updatePassword(@EntityParam @RequestBody UserDTO dto) {
        User user = userService.findById(dto.getId());

        String old = ShiroUtil.encrypt(dto.getOldPassword(), user.getSalt());
        if(!old.equals(user.getPassword())){
            return JsonResponse.error("原密码不正确");
        }
        String salt = ShiroUtil.getRandomSalt();
        String newPassword = ShiroUtil.encrypt(dto.getPassword(), salt);
        user.setPassword(newPassword);
        user.setSalt(salt);
        userService.save(user);
        Subject subject = SecurityUtils.getSubject();
        //注销
        subject.logout();
        return JsonResponse.success("修改成功");
    }


    @GetMapping("/resetPassword/page/{id}")
    public String toResetPassword(@PathVariable("id") User user, Model model){
        model.addAttribute("user",user);
        return PAGE_PATH+"/resetPassword";
    }


    @ResponseBody
    @PostMapping("/resetPassword")
    public JsonResponse resetPassword(@EntityParam @RequestBody User user) {
        User beUser = userService.findById(user.getId());
        // 对密码进行加密
        String salt = ShiroUtil.getRandomSalt();
        String encrypt = ShiroUtil.encrypt(user.getPassword(), salt);
        beUser.setPassword(encrypt);
        beUser.setSalt(salt);
        if(StringUtils.isNotBlank(user.getPhone())){
            beUser.setPhone(user.getPhone());
            //首页修改需重新登录
            Subject subject = SecurityUtils.getSubject();
            //注销
            subject.logout();
        }
        // 保存数据
        userService.save(beUser);
        return JsonResponse.success();
    }


}
